package copyengine.network.roomStructure.executeLayer
{
	import copyengine.network.roomStructure.CENetworkCommandNotification;
	import copyengine.network.roomStructure.executeLayer.component.CENetworkExecuteHandleSubEncryptionComponent;
	import copyengine.network.roomStructure.executeLayer.component.CENetworkExecuteHandleSubErrorHandleComponent;
	import copyengine.network.roomStructure.executeLayer.component.CENetworkExecuteHandleSubP2PComponent;
	import copyengine.network.roomStructure.executeLayer.impl.rtmfp.RTMFPExecuteWarp;
	import copyengine.network.roomStructure.executeLayer.impl.socket.SocketExecuteWarp;
	import copyengine.utils.CENestMediatorBasic;
	import copyengine.utils.UUIDFactory;
	import copyengine.utils.debug.CELog;

	import flash.events.Event;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;

	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;

	public final class CENetworkRoomExecuteHandleMediator extends CENestMediatorBasic implements IExecuteHandle
	{
		private var rtmfpExecuteWarp:RTMFPExecuteWarp;
		private var socketExecuteWarp:SocketExecuteWarp;

		//ByteArray加密解密模块
		private var subEncryptionComponent:CENetworkExecuteHandleSubEncryptionComponent;
		//Error处理模块
		private var subErrorHandleComponent:CENetworkExecuteHandleSubErrorHandleComponent;
		//P2P模块
		private var subP2PBoostingComponent:CENetworkExecuteHandleSubP2PComponent;

		public function CENetworkRoomExecuteHandleMediator()
		{
			super();
		}

		override public function onRegister():void
		{
			rtmfpExecuteWarp = new RTMFPExecuteWarp();
			rtmfpExecuteWarp.initialize(this);

			socketExecuteWarp = new SocketExecuteWarp();
			socketExecuteWarp.initialize(this);

			subEncryptionComponent = new CENetworkExecuteHandleSubEncryptionComponent();
			subErrorHandleComponent = new CENetworkExecuteHandleSubErrorHandleComponent();
			subP2PBoostingComponent = new CENetworkExecuteHandleSubP2PComponent();
			subP2PBoostingComponent.initialize(rtmfpExecuteWarp);
		}

		override public function listNotificationInterests():Array
		{
			return [
				CENetworkRoomExecuteHandleNotification.RECEIVE_START_CONNECT_SOCKET_SERVER,
				CENetworkRoomExecuteHandleNotification.RECEIVE_END_CONNECT_SOCKET_SERVER,
				CENetworkRoomExecuteHandleNotification.RECEIVE_SEND_DATA_MIX,
				CENetworkRoomExecuteHandleNotification.RECEIVE_SEND_DATA_SOCKET,
				CENetworkRoomExecuteHandleNotification.RECEIVE_START_P2P_BOOSTING,
				CENetworkRoomExecuteHandleNotification.RECEIVE_END_P2P_BOOSTING,
				];
		}

		override public function handleNotification(notification:INotification):void
		{
			switch (notification.getName())
			{
				//连接Socket
				case CENetworkRoomExecuteHandleNotification.RECEIVE_START_CONNECT_SOCKET_SERVER:
					doStartConnectSocketExecute(notification.getBody()["url"], notification.getBody()["prot"]);
					break;
				//断开Socket
				case CENetworkRoomExecuteHandleNotification.RECEIVE_END_CONNECT_SOCKET_SERVER:
					doStartDisconnectSocketExecute();
					break;
				//发送数据
				case CENetworkRoomExecuteHandleNotification.RECEIVE_SEND_DATA_MIX:
				case CENetworkRoomExecuteHandleNotification.RECEIVE_SEND_DATA_SOCKET:
					doSendData(notification.getName(), notification.getBody());
					break;
				//开始P2P加速
				case CENetworkRoomExecuteHandleNotification.RECEIVE_START_P2P_BOOSTING:
					doStartP2PBoosting(notification.getBody()["groupName"],
									   notification.getBody()["rtmfpURL"],
									   notification.getBody()["allSocketNeighborIDsArray"],
									   notification.getBody()["playerID"]);
					break;
				//结束P2P加速
				case CENetworkRoomExecuteHandleNotification.RECEIVE_END_P2P_BOOSTING:
					doEndP2PBoosting();
					break;
			}
		}

		private function doSendData(_sendDataType:String, _arg:Object):void
		{
			var command:uint = _arg["command"];
			var commandArg:Object = _arg["commandArg"]
			var forwardDataObj:Object = _arg["forwardData"];
			var forwardDataByteArray:ByteArray;

			//============
			//==P2P 处理
			//============
			if (_sendDataType == CENetworkRoomExecuteHandleNotification.RECEIVE_SEND_DATA_MIX &&
				subP2PBoostingComponent.isBoosting())
			{
				//如果使用P2P方式加速,则ForwardData一定不为空
				subP2PBoostingComponent.addFingerprintInForwardData(forwardDataObj);
			}

			//==============
			//==通用处理
			//==============
			if (forwardDataObj)
			{
				//加密+压缩数据包
				forwardDataByteArray = subEncryptionComponent.encryptionForwardData(forwardDataObj);
			}
			commandArg["receiverIDs"] = [];


			if (_sendDataType == CENetworkRoomExecuteHandleNotification.RECEIVE_SEND_DATA_MIX &&
				subP2PBoostingComponent.isBoosting())
			{
				var allSocketSendIDs:Array = subP2PBoostingComponent.getAllSocketSendIDs();
				//有可能所有ID全部可以用P2P方式发送
				if (allSocketSendIDs.length > 0)
				{
					//如果使用P2P加速则需要指定转发的ID
					commandArg["receiverIDs"] = allSocketSendIDs;
					socketExecuteWarp.sendData(command, commandArg, forwardDataByteArray);
				}

				//同时用两个Channel发送数据
				//!!!!注意 : 因为RTMFP模式不通过Server转发,所以在发送前先把数据包的Command改为接收到交换数据
				//Socket会由服务器端改变Command
				rtmfpExecuteWarp.sendData(CENetworkCommandNotification.S_RESERVE_COMMAND_RECEIVE_TRANSPOND_DATA,
										  commandArg,
										  forwardDataByteArray);
			}
			else
			{
				socketExecuteWarp.sendData(command, commandArg, forwardDataByteArray);
			}
		}

		public function onReceiveExecuteData(_warpType:int, _command:int, _commandArg:Object = null, _forwardData:ByteArray = null):void
		{
			var forwardDataObj:Object;
			if (_forwardData && _forwardData.length > 0)
			{
				forwardDataObj = subEncryptionComponent.decryptionForwardData(_forwardData);
			}

			var isCanContinueProgress:Boolean = true;
			if (subP2PBoostingComponent.isBoosting())
			{
				isCanContinueProgress = subP2PBoostingComponent.onReceiveData(_command, _commandArg, forwardDataObj);
			}

			if (isCanContinueProgress)
			{
				sendNotification(CENetworkRoomExecuteHandleNotification.SEND_RECEIVE_INCOMING_DATA,
								 {
									 command:_command,
									 commandArg:_commandArg,
									 forwardData:forwardDataObj
								 });
			}
		}

		//=======================
		//==Socket Connect&Disconnect
		//=======================

		private function doStartConnectSocketExecute(_url:String, _port:int):void
		{
			if (!socketExecuteWarp.isEnable())
			{
				socketExecuteWarp.connect(_url, _port);
			}
			else
			{
				CELog.err("CENetworkRoomExecuteHandle->doStartConnectSocketExecute socket server already connected");
				onExecuteConnected(CENetworkRoomModelConfig.EXECUTE_WARP_TYPE_SOCKET);
			}
		}

		private function doStartDisconnectSocketExecute():void
		{
			if (socketExecuteWarp.isEnable())
			{
				socketExecuteWarp.disconnect();
			}
			else
			{
				CELog.err("CENetworkRoomExecuteHandle->doStartDisconnectSocketExecute socket server already disconnect");
				onExecuteDisconnected(CENetworkRoomModelConfig.EXECUTE_WARP_TYPE_SOCKET);
			}
		}

		//======================
		//==RTMFP Connect&Disconnect
		//======================

		private function doStartP2PBoosting(_groupName:String,
											_rtmfpURL:String,
											_allSocketNeighborIDsArray:Array,
											_playerID:String):void
		{
			subP2PBoostingComponent.startP2PBoosting(_groupName, _rtmfpURL, _allSocketNeighborIDsArray, _playerID);
		}

		private function doEndP2PBoosting():void
		{
			subP2PBoostingComponent.endP2PBoosting();
		}

		//=================
		//==Closed && Connected
		//==================

		public function onExecuteConnected(_warpType:int):void
		{
			if (_warpType == CENetworkRoomModelConfig.EXECUTE_WARP_TYPE_SOCKET)
			{
				sendNotification(CENetworkRoomExecuteHandleNotification.SEND_SOCKET_SERVER_CONNECTED);
			}
			else if (_warpType == CENetworkRoomModelConfig.EXECUTE_WARP_TYPE_RTMFP)
			{
				//回调RTMFPComponent
				subP2PBoostingComponent.onRTMFPServerConnect();
			}
			else
			{
				CELog.err("CENetworkRoomExecuteHandle->onExecuteConnected unknow warpType : " + _warpType);
			}
		}

		public function onExecuteDisconnected(_warpType:int):void
		{
			if (_warpType == CENetworkRoomModelConfig.EXECUTE_WARP_TYPE_SOCKET)
			{
				sendNotification(CENetworkRoomExecuteHandleNotification.SEND_SOCKET_SERVER_CLOSED);
			}
			else if (_warpType == CENetworkRoomModelConfig.EXECUTE_WARP_TYPE_RTMFP)
			{
				//回调RTMFPComponent
				subP2PBoostingComponent.onRTMFPServerClosed();
			}
			else
			{
				CELog.err("CENetworkRoomExecuteHandle->onExecuteConnectClosed unknow warpType : " + _warpType);
			}

		}

		//===============
		//==ERROR
		//===============

		public function onExecuteError(_warpType:int, e:Event):void
		{
			subErrorHandleComponent.onExecuteError(_warpType, e);
		}


	}
}
